﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace FlowDiagram.Core
{
    public abstract class BaseNode
    {
        #region 变量

        protected List<BaseNode> _childs = null;
        protected ManualResetEvent _selfSync = null;
        protected ManualResetEvent _externalSync = null;
        protected bool _haveExternalSync = false;

        #endregion
        #region 属性

        public string GUID { set; get; }
        public string Name { set; get; }

        public List<BaseNode> Childs
        {
            get
            {
                return _childs = _childs ?? new List<BaseNode>();
            }
        }

        public BaseNode Parent { set; get; }

        public bool Enbale { set; get; }
        #endregion
        #region 事件

        public event EventHandler<BaseNodeEventArgs> PreDowork;
        protected virtual void onPreDowork(object sender, BaseNodeEventArgs e)
        {
            if (PreDowork != null)
                PreDowork(sender, e);
            else
                throw new NotImplementedException();
        }

        public event EventHandler<BaseNodeEventArgs> DoworkDone;
        protected virtual void onDoworkDone(object sender, BaseNodeEventArgs e)
        {
            if (DoworkDone != null)
                DoworkDone(sender, e);
            else
                throw new NotImplementedException();
        }

        public event EventHandler<BaseNodeEventArgs> ExceptionOccured;
        protected virtual void onExceptionOccured(object sender, BaseNodeEventArgs e)
        {
            if (ExceptionOccured != null)
                ExceptionOccured(sender, e);
            else
                throw new NotImplementedException();
        }

        public event EventHandler<BaseNodeEventArgs> WarnningOccured;
        protected virtual void onWarnningOccured(object sender, BaseNodeEventArgs e)
        {
            if (WarnningOccured != null)
                WarnningOccured(sender, e);
            else
                throw new NotImplementedException();
        }

        public event Func<TaskResults, TaskResults> Dowork;
        #endregion
        #region 构造函数
        public BaseNode()
        { }
        #endregion
        #region 自定义方法
        #region 公有方法
        protected virtual TaskResults DoWorkFunc(TaskResults tr)
        {
            return tr;
        }

        protected virtual void StartDowork(TaskResults tr)
        {
            Task p = Task.Factory.StartNew(() =>
            {
                #region DO
                try
                {

                    #region 重置信号
                    _selfSync.Reset();
                    _externalSync.Reset();
                    #endregion

                    //等待父节点同步信号
                    if (Parent != null)
                        Parent._selfSync.WaitOne();
                    //等待外部信号
                    if (_haveExternalSync)
                        _externalSync.WaitOne();
                    //PreWork
                    this.onPreDowork(this, new BaseNodeEventArgs());

                    Task t1 = Task.Factory.StartNew(() =>
                    { //Doing...
                        DoWorkFunc(tr);
                    });
                    Task t2 = Task.Factory.StartNew(() =>
                    {
                        foreach (BaseNode bn in _childs)
                        {
                            bn.StartDowork(tr);
                        }
                    });

                    //WorkDone
                    this.onPreDowork(this, new BaseNodeEventArgs());
                    //打开同步信号
                    _selfSync.Set();
                }
                catch (Exception ex)
                {
                    this.onExceptionOccured(this, new BaseNodeEventArgs() { Ex = ex });
                    tr.IsSuccess = false;
                    tr.ErrorMsg.Enqueue(ex.ToString());
                }
                #endregion
            });
        }

        #endregion
        #region 私有方法



        #endregion
        #endregion
    }
}
